#include "pch.h"
#include "string_tools.h"


StringTools* StringTools::tools_ = new StringTools;


std::string StringTools::UnicodeToUTF8(const std::wstring& wstr)
{
	std::string ret;
	try {
		std::wstring_convert< std::codecvt_utf8<wchar_t> > wcv;
		ret = wcv.to_bytes(wstr);
	}
	catch (const std::exception& e) {
		std::cerr << e.what() << std::endl;
	}
	return ret;
	char* bbb = nullptr;
	char aaa[100] = {1,2,3,4,5,6};
	string str;
	str = bbb;
}

std::wstring StringTools::UTF8ToUnicode(const char* str)
{
	std::wstring ret;
	try {
		std::wstring_convert< std::codecvt_utf8<wchar_t> > wcv;
		ret = wcv.from_bytes(str);
	}
	catch (const std::exception& e) {
		std::cerr << e.what() << std::endl;
	}
	return ret;
}

std::string StringTools::UnicodeToANSI(const std::wstring& wstr)
{
	std::string ret;
	std::mbstate_t state = {};
	const wchar_t* src = wstr.data();
	size_t len = std::wcsrtombs(nullptr, &src, 0, &state);
	if (static_cast<size_t>(-1) != len) {
		std::unique_ptr< char[] > buff(new char[len + 1]);
		len = std::wcsrtombs(buff.get(), &src, len, &state);
		if (static_cast<size_t>(-1) != len) {
			ret.assign(buff.get(), len);
		}
	}
	return ret;
}

std::wstring StringTools::ANSIToUnicode(const std::string& str)
{
	std::wstring ret;
	std::mbstate_t state = {};
	const char* src = str.data();

	size_t len = std::mbsrtowcs(nullptr, &src, 0, &state);
	if (static_cast<size_t>(-1) != len) {
		std::unique_ptr< wchar_t[] > buff(new wchar_t[len + 1]);
		len = std::mbsrtowcs(buff.get(), &src, len, &state);
		if (static_cast<size_t>(-1) != len) {
			ret.assign(buff.get(), len);
		}
	}
	return ret;
}

std::string StringTools::UTF8ToANSI(const std::string& str)
{
	return UnicodeToANSI(UTF8ToUnicode(str.c_str()));
}

std::string StringTools::ANSIToUTF8(const std::string& str)
{
	return UnicodeToUTF8(ANSIToUnicode(str));
}


std::string StringTools::StringToUpper(const std::string& source)
{
	std::string ret;
	transform(source.begin(), source.end(), ret.begin(), ::toupper);
	return ret;
}

std::string StringTools::StringToLower(const std::string& source)
{
	std::string ret;
	transform(source.begin(), source.end(), ret.begin(), ::tolower);
	return ret;
}

int StringTools::StringToInt(const std::string& source)
{
	return stoi(source.c_str());
}

bool StringTools::StringToBool(const std::string& source)
{
	return stoi(source.c_str());
}

char* StringTools::StringToArray(const std::string& str)
{
	char *ret = new char[str.size()+1];
	strcpy(ret, str.c_str());
	return ret;
}

std::string StringTools::StringFromInt(int source)
{
	std::string ret;
	char* target = nullptr;
	sprintf(target,"%d", source);
	ret = target;
	return ret;
}

std::vector<std::string> StringTools::StringSplit(const std::string& source, const std::string& interval)
{
	std::vector<std::string> ret;
	char* target = new char[source.size() + 1];
	strcpy(target, source.c_str());
	char* d = new char[interval.length() + 1];
	strcpy(d, interval.c_str());

	char* p = strtok(target, d);
	while (p) {
		std::string s = p; //分割得到的字符串转换为string类型
		ret.push_back(s); //存入结果数组
		p = strtok(NULL, d);
	}
	return ret;
}

std::string StringTools::DeleteSpecString_One(const std::string& source, const char& specstr)
{
	std::string ret = source;
	ret.erase(source.find_first_of(specstr), 1);
	return ret;
}

std::string StringTools::DeleteSpecString_All(const std::string& source, const char& specstr)
{
	std::string ret = source;
	ret.erase(std::remove(ret.begin(), ret.end(), specstr), ret.end());
	return ret;
}

std::string  StringTools::DeleteSpecString_All(const std::string& source, const std::string& specstr)
{
	std::string ret = source;
	for (std::string::size_type pos = 0; pos != std::string::npos;) {
		if ((pos = ret.find(specstr, pos)) != std::string::npos)
			ret.replace(pos, specstr.length(), "");
		else break;
	}
	return ret;
}

std::string StringTools::DeleteSpecString_Left(const std::string& source, const std::string& specstr)
{
	std::string ret = source;
	for (std::string::size_type pos = 0; pos != std::string::npos;) {
		if ((pos = ret.find(specstr, pos)) != std::string::npos) {
			if (pos == 0)
				return "";
			ret = ret.substr(pos, ret.size()-1);
			return ret;
		}

	}
	return ret;
}

std::string StringTools::DeleteSpecString_Right(const std::string& source, const std::string& specstr)
{
	std::string ret = source;
	for (std::string::size_type pos = 0; pos != std::string::npos;) {
		if ((pos = ret.find(specstr, pos)) != std::string::npos) {
			if (pos == 0)
				return "";
			ret = ret.substr(0, pos - 1);
			return ret;
		}

	}
	return ret;
}

std::string StringTools::ReplaceSpecString_First(const std::string& source, const std::string& specstr, const std::string& target)
{
	std::string ret = source;
	ret = ret.replace(ret.find(specstr), specstr.size(), target);
	return ret;
}

std::string StringTools::ReplaceSpecString_Last(const std::string& source, const std::string& specstr, const std::string& target)
{
	std::string ret = source;
	ret = ret.replace(ret.find_last_of(specstr), specstr.size(), target);
	return ret;
}

std::string StringTools::ReplaceSpecString_All(const std::string& source, const std::string& specstr, const std::string& target)
{
	std::string ret = source;
	for (std::string::size_type pos = 0; pos != std::string::npos; pos += target.length()) {
		if ((pos = ret.find(specstr, pos)) != std::string::npos)
			ret.replace(pos, specstr.length(), target);
		else break;
	}
	return ret;
}